import { useState, useEffect, useCallback } from "react";
import { ScrollView, Text, View, ToastAndroid, StyleSheet } from "react-native";
import { Module, AudioManage, LuminanceManage } from "@/utils/nativeModules";
import Btn from "@/components/Btn";
import { TextInput } from "react-native-paper";
import getDeviceInfo from "@/utils/getDeviceInfo";
import fso from "@/utils/FileOperate/operate";
import { sliceFileSqlh } from "@/sqlite/exports";
import Slider from "@react-native-community/slider";
import RNFS from "react-native-fs";

// @ts-ignore
import DialogAndroid from "react-native-dialogs";

// 支持 cron 表达式, 但是在后台无法执行, 切到前台则会马上执行
// https://github.com/Hexagon/croner
import { Cron } from "croner";
import { emitter, eventMap, addListener, removeListener, emit } from "@/utils/event";
import theme from "@/styles/theme";
import globalMethods from "@/GlobalMethodProvider";
import config from "@/config";
import { handleCmdMethod } from "@/utils/websocket/handleWSCmd";
import stateCodeMap from "@/utils/websocket/stateCodeMap";

// 后台可以执行但是不支持 cron 表达式
// https://github.com/ocetnik/react-native-background-timer
let job: Cron | null = null;

const SystemTest = () => {
  const [state, _setState] = useState({
    volume: 0,
    luminance: 0,
    time: new Date().toLocaleTimeString(),
    // https://cron.qqe2.com/
    // 0 30 8 * * ?
    cron: "0 12 14 * * ?"
  });

  // 通用更新状态单个
  const setState = useCallback((field: keyof typeof state, val: any) => {
    _setState(_state => {
      return { ..._state, [field]: val };
    });
  }, []);

  // 通用更新状态(对象)
  const setObjState = useCallback((obj: Partial<typeof state>) => {
    _setState(_state => {
      return { ..._state, ...obj };
    });
  }, []);

  const getSysVolume = useCallback(() => {
    AudioManage.getCurrentVolume().then(res => {
      console.log("getSysVolume: ", res);
      if (res === 0 || res) {
        setState("volume", res);
      } else {
        ToastAndroid.show(`音量获取失败`, ToastAndroid.SHORT);
      }
    });
  }, [setState]);

  const setSysVolume = (volume: number) => {
    AudioManage.setCurrentVolume(volume).then(res => {
      console.log("setSysVolume: ", res);
      if (res) {
        ToastAndroid.show(`音量设置失败了`, ToastAndroid.SHORT);
      } else {
        setState("volume", volume);
      }
    });
  };

  const getSysLuminance = useCallback(() => {
    LuminanceManage.getLuminance().then(res => {
      console.log("getSysLuminance", res);
      if (res === 0 || res) {
        setState("luminance", res);
      } else {
        ToastAndroid.show(`亮度获取失败`, ToastAndroid.SHORT);
      }
    });
  }, [setState]);

  const setSysLuminance = (val: number) => {
    LuminanceManage.setLuminance(val).then(res => {
      console.log("setSysLuminance: ", res);
      if (res) {
        ToastAndroid.show(`亮度设置失败`, ToastAndroid.SHORT);
      } else {
        setState("luminance", val);
      }
    });
  };

  useEffect(() => {
    fso.clearTodayFile();
  }, []);

  useEffect(() => {
    getSysVolume();
    getSysLuminance();
  }, [getSysVolume, getSysLuminance]);

  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>音量设置</Text>
      <View style={styles.item}>
        <Btn text="获取系统音量" type="primary" onClick={getSysVolume} />
        <Slider
          style={{ width: 200, height: 30 }}
          value={state.volume}
          minimumValue={0}
          maximumValue={100}
          step={1}
          minimumTrackTintColor={theme.primary}
          thumbTintColor={theme.primary}
          onSlidingComplete={num => setSysVolume(num)}
        />
        <Text>当前值: {state.volume}</Text>
      </View>

      <Text style={styles.title}>亮度设置</Text>
      <View style={styles.item}>
        <Btn text="获取系统亮度" type="primary" onClick={getSysLuminance} />
        <Slider
          style={{ width: 200, height: 30 }}
          value={state.luminance}
          minimumValue={0}
          maximumValue={100}
          step={1}
          minimumTrackTintColor={theme.primary}
          thumbTintColor={theme.primary}
          onSlidingComplete={num => setSysLuminance(num)}
        />
        <Text>当前值: {state.luminance}</Text>
      </View>

      <Text style={styles.title}>其他设置</Text>
      <View style={styles.item}>
        <Btn
          text="设备信息"
          type="primary"
          onClick={() => {
            getDeviceInfo()
              .then(res => {
                console.log("设备信息: ", res);
              })
              .catch(err => {
                console.log("err: ", err);
              });
          }}
        />
        <Btn
          text="判断是否ROOT"
          type="primary"
          onClick={() => {
            Module.isRoot()
              .then(res => {
                console.log("是否root: ", res);
                globalMethods.$success(res ? "有root" : "没有root");
              })
              .catch(err => {
                console.log("err: ", err);
              });
          }}
        />
        <Btn
          text="重启app"
          type="primary"
          onClick={() => {
            Module.restartApp();
          }}
        />
        <Btn
          type="primary"
          text="shell重启app"
          onClick={async () => {
            try {
              const appInfo = await Module.getAppInfo();
              if (appInfo) {
                const res = await Module.execShell(
                  `am force-stop ${appInfo.packageName} && am start -n ${appInfo.packageName}/.MainActivity`,
                  true
                );
                if (res?.exitValue === 0) {
                  globalMethods.$success("卸载完成");
                } else {
                  globalMethods.$error("发生了错误: " + res?.stderr);
                }
              } else {
                globalMethods.$error("App信息获取失败");
              }
            } catch (err) {
              console.log("err: ", err);
              globalMethods.$error("发生了错误: " + err);
            }
          }}
        />
        <Btn
          text="重启系统"
          type="primary"
          onClick={() => {
            Module.reboot().then(res => {
              if (res) {
                console.log("重启失败: ", res);
              } else {
                console.log("重启成功");
              }
            });
          }}
        />
        <Btn
          text="修改系统时间"
          type="primary"
          onClick={async () => {
            try {
              const { action, text } = await DialogAndroid.prompt(
                "修改系统的时间",
                "输入需要修改系统的时间(YYYYMMDD.HHmmss)",
                {
                  defaultValue: "20210101.120000",
                  cancelable: false
                }
              );

              if (action === DialogAndroid.actionPositive) {
                if (text) {
                  const res = await Module.setSystemTime(text);
                  console.log("res: ", res);
                  globalMethods.$success("执行响应: " + JSON.stringify(res, null, 2));
                } else {
                  globalMethods.$warning("执行的命令不能为空");
                }
              }
            } catch (err) {
              console.log("err: ", err);
              globalMethods.$error("发生了错误: " + err);
            }
          }}
        />
        <Btn
          type="primary"
          text="正常安装APK"
          onClick={async () => {
            try {
              const { action, text } = await DialogAndroid.prompt("安装apk", "输入apk文件的地址", {
                defaultValue: `${RNFS.DownloadDirectoryPath}/mlkj_m180_app_0.0.1_2024_03_05.apk`,
                cancelable: false
              });

              const installApkPath = text;

              const exists = await fso.exists(installApkPath);
              if (!exists) {
                globalMethods.$error("文件不存在: " + installApkPath);
                return;
              }

              // 这种方式会弹出安装提示, 在高版本需要用户点击安装才行,
              // 但是在省行 Android 7 测试大屏是会自动安装并且重新打开的
              const res = await Module.actionViewIntent(installApkPath, "apk");
              fso.info("安装响应: ", res);
            } catch (err) {
              console.log("err: ", err);
              globalMethods.$error("发生了错误: " + err);
            }
          }}
        />
        <Btn
          type="primary"
          text="静默安装APK"
          onClick={async () => {
            try {
              const { action, text } = await DialogAndroid.prompt("安装apk", "输入apk文件的地址", {
                defaultValue: `${RNFS.DownloadDirectoryPath}/mlkj_m180_app_0.0.2_2024_03_05.apk`,
                cancelable: false
              });

              const installApkPath = text;

              const exists = await fso.exists(installApkPath);
              if (!exists) {
                globalMethods.$error("文件不存在: " + installApkPath);
                return;
              }

              // 可以安装其他的app, 但是不能安装当前的app, 会导致应用闪退
              fso.info("静默安装APK: ", installApkPath);
              const res = await Module.execShell(`pm install -r ${installApkPath}`, true);

              fso.info("静默安装响应: ", res);
              if (res) {
                if (res.exitValue === 0) {
                  fso.info("静默安装成功, 正在重启app");
                  globalMethods.$showMessage({
                    type: 'toast',
                    message: "静默安装成功",
                  });
                } else {
                  fso.warn("静默安装失败: ", res.stdout);
                  globalMethods.$showMessage({
                    type: 'toast',
                    message: res.stdout,
                  });
                }
              } else {
                fso.warn("静默安装失败: ", res);
                globalMethods.$showMessage({
                  type: 'toast',
                  message: '静默安装失败',
                });
              }
            } catch (err) {
              console.log("err: ", err);
              globalMethods.$showMessage({
                type: 'toast',
                message: "发生了错误: " + err,
              });
            }
          }}
        />
      </View>

      <Text style={styles.title}>文件操作</Text>
      <View style={styles.item}>
        <Btn
          text="目录信息"
          type="primary"
          onClick={() => {
            console.log("RNFS: ", RNFS);
            console.log("fso: ", fso);
          }}
        />
        <Btn
          text="日志写入"
          type="primary"
          onClick={() => {
            Promise.all([
              // RNFS.appendFile(`${fso.logDir}/2023_04_12.log`, "日志"),
              // RNFS.appendFile(`${fso.logDir}/2023_02_12.log`, "日志"),
              // RNFS.appendFile(`${fso.logDir}/2022_02_12.log`, "日志"),
              // RNFS.appendFile(`${fso.logDir}/2023_04_10.log`, "日志"),

              fso.info("普通的记录信息日志"),
              fso.warn("这是一个警告日志"),
              fso.error("发生了错误日志".repeat(10)),
              fso.warn("这是一个警告日志"),
              fso.error("发生了错误日志"),
              fso.info("普通的记录信息日志")
            ])
              .then(res => {
                console.log("写入成功: ", res);
              })
              .catch(err => {
                console.log("写入失败了: ", err);
              });
          }}
        />
        <Btn
          text="读取当天的日志"
          type="primary"
          onClick={() => {
            fso
              .readTodayFile()
              .then(res => {
                console.log(res);
              })
              .catch(err => {
                console.log("err: ", err);
              });
          }}
        />
        <Btn
          text="清空当天日志"
          type="primary"
          onClick={() => {
            fso
              .clearTodayFile()
              .then(res => {
                console.log("清除成功", res);
                globalMethods.$success("清除成功");
              })
              .catch(err => {
                console.log("清除失败", err);
                globalMethods.$error("清除失败");
              });
          }}
        />
        <Btn
          text="清除三十天之前的文件"
          type="primary"
          onClick={() => {
            fso
              .clearBeforeDayFile()
              .then(result => {
                console.log("result: ", result);
              })
              .catch(err => {
                console.log(err.message, err.code);
              });
          }}
        />
        <Btn
          text="截图"
          type="primary"
          onClick={() => {
            fso
              .captureScreen()
              .then(res => {
                console.log("res: ", res);
              })
              .catch(err => {
                console.log("截图失败: ", err);
              });
          }}
        />
        <Btn
          text="文件上传"
          type="primary"
          onClick={async () => {
            console.log("上传当天日志");

            fso
              .uploadFile({
                url: "http://192.168.1.101:8100/uploadFile",
                method: "POST",
                // fileName: "2023_07_30.log",
                fileName: "这是上传文件.log",
                formDataKey: "file",
                filePath: fso.getTodayFile()
              })
              .then(res => {
                console.log("文件上传成功: ", res);
              })
              .catch(err => {
                console.log("文件上传失败: ", err);
              });
          }}
        />
        <Btn
          text="文件下载"
          type="primary"
          onClick={async () => {
            try {
              const item = {
                isDown: "1",
                isChunkDown: "1",
                downFileUrl:
                  "https://api.xjfw.top/m000/minio/view/m180/b93f67212a3141f76edb4fc24d0aa3d3.mp4?name=坐不下.mp4?name=坐不下.mp4&isChunk=0",
                // "https://api.xjfw.top/m000/minio/down/m180/b93f67212a3141f76edb4fc24d0aa3d3.mp4?name=坐不下.mp4?name=坐不下.mp4&isChunk=0",
                sort: 1,
                resolution: "480*480",
                fileName: "b93f67212a3141f76edb4fc24d0aa3d3.mp4",
                startTime: "08:30:00",
                remarks: null,
                endTime: "08:30:15",
                size: "1066094",
                officeName: "广东省分行",
                duration: "00:00:15",
                putLibTime: "2023-09-27 14:24:59",
                sourceId: "1706918415707365377",
                officeCode: "44000000",
                isShim: "2",
                downFileToNativePath:
                  "/storage/emulated/0/Download/mlkj-m180/resource/000004/b93f67212a3141f76edb4fc24d0aa3d3.mp4",
                code: "000003",
                type: "4",
                file: "/api/m000/minio/down//m180/b93f67212a3141f76edb4fc24d0aa3d3.mp4?name=坐不下.mp4?name=坐不下.mp4&isChunk=0",
                isUnAudit: "0",
                status: "0",
                parentCode: "000004",
                name: "坐不下.mp4",
                auditFlag: "0",
                id: 35
              };

              const time = Date.now();

              const res = await fso.downFile({
                // url: item.downFileUrl,
                url: "http://10.111.1.28:8900/downloadFile?file=大文件.mp4",
                method: "GET",
                title: "网点多媒体下载",
                description: `正在下载${item.name}`,
                // downFileToNativePath: item.downFileToNativePath
                downFileToNativePath: "/storage/emulated/0/Download/mlkj-m180/resource/000004/大文件.mp4"
              });
              console.log(`${res ? "未" : ""}下载完成, 共用时: ${Date.now() - time}ms`);
            } catch (err) {
              if (err instanceof Error) {
                console.log("err: ", err.message);
              } else {
                console.log("err: ", err);
              }
            }
          }}
        />
        <Btn
          text="分片下载"
          type="primary"
          onClick={async () => {
            try {
              const item = {
                isDown: "1",
                isChunkDown: "1",
                downFileUrl:
                  "https://api.xjfw.top/hinge-m180/m000/minio/down//m180/b93f67212a3141f76edb4fc24d0aa3d3.mp4?name=坐不下.mp4?name=坐不下.mp4&isChunk=0",
                sort: 1,
                resolution: "480*480",
                fileName: "b93f67212a3141f76edb4fc24d0aa3d3.mp4",
                startTime: "08:30:00",
                remarks: null,
                endTime: "08:30:15",
                size: "1066094",
                officeName: "广东省分行",
                duration: "00:00:15",
                putLibTime: "2023-09-27 14:24:59",
                sourceId: "1706918415707365377",
                officeCode: "44000000",
                isShim: "2",
                downFileToNativePath:
                  "/storage/emulated/0/Download/mlkj-m180/resource/000004/b93f67212a3141f76edb4fc24d0aa3d3.mp4",
                code: "000003",
                type: "4",
                file: "/api/m000/minio/down//m180/b93f67212a3141f76edb4fc24d0aa3d3.mp4?name=坐不下.mp4?name=坐不下.mp4&isChunk=0",
                isUnAudit: "0",
                status: "0",
                parentCode: "000004",
                name: "坐不下.mp4",
                auditFlag: "0",
                id: 1
              };

              const time = Date.now();

              const res = await fso.downFile({
                url: item.downFileUrl,
                method: "GET",
                title: "下载素材",
                description: `网点多媒体下载`,
                downFileToNativePath: item.downFileToNativePath
              });

              // const res = await fso.sliceDownload({
              //   url: item.downFileUrl,
              //   method: "GET",
              //   fileSize: Number(item.size),
              //   rangeSize: config.downMaterialChunkSize,
              //   downloadFilePath: item.downFileToNativePath,
              //   restDownload: true,
              //   // testError: true,
              //   onSomeRestDownload(fileList) {
              //     console.log("本地存在还有未下载完成的切片文件", JSON.stringify(fileList));
              //   },
              //   onCurrentRestDownload(fileList) {
              //     console.log(`要下载的 ${this.downloadFilePath} 有未下载成功的部分, 继续下载剩余的部分`);
              //   },
              //   onSliceFileDownError(fileInfo) {
              //     console.log(`${fileInfo.targetFilePath} 下载失败`);
              //   },
              //   onBeforeSliceDownFile(opt) {
              //     console.log("开始下载: ", opt);
              //   },
              //   onAfterSliceDownFile(opt) {
              //     console.log("下载完成: ", opt);
              //   },
              //   onUnfinishFileDown(opt) {
              //     console.log(`分片文件未下载完成`, opt);
              //   },
              //   onBuildSliceFile(opt) {
              //     console.log(`下载完成, 开始合并分片文件`, opt);
              //   }
              // });

              console.log(`${res ? "未" : ""}下载完成, 共用时: ${Date.now() - time}ms`);
            } catch (err) {
              if (err instanceof Error) {
                console.log("err: ", err.message);
              } else {
                console.log("err: ", err);
              }
            }
          }}
        />
        <Btn
          text="清空分片文件信息"
          type="primary"
          onClick={async () => {
            try {
              if (sliceFileSqlh) {
                const res = await sliceFileSqlh.clearTable();
                console.log("res: ", res);
              } else {
                console.log("测试数据库初始化失败");
              }
            } catch (err) {
              if (err instanceof Error) {
                console.log("err: ", err.message);
              } else {
                console.log("err: ", err);
              }
            }
          }}
        />
      </View>

      <Text style={styles.title}>指令测试</Text>
      <View style={styles.item}>
        <Btn
          text="下载安装包"
          type="primary"
          onClick={async () => {
            try {
              const res = await handleCmdMethod[stateCodeMap.UPDATE_APP]({
                data: {
                  updateVersionUrl: "http://1.12.69.30:9000/m180/apks/test.apk"
                },
                cmd: stateCodeMap.UPDATE_APP,
                msg: ""
              });
              console.log("res: ", res);
            } catch (err) {
              console.log("err: ", err);
            }
          }}
        />
        <Btn
          text="截图"
          type="primary"
          onClick={async () => {
            try {
              const res = await handleCmdMethod[stateCodeMap.CAPTURE]({
                data: {
                  batchId: "999"
                },
                cmd: stateCodeMap.CAPTURE,
                msg: ""
              });
              console.log("res: ", res);
            } catch (err) {
              console.log("err: ", err);
            }
          }}
        />
        <Btn
          type="primary"
          text="测试删除素材"
          onClick={async () => {
            try {
              const res = await handleCmdMethod[stateCodeMap.REMOVE_RESOURCE]({
                msg: "",
                cmd: stateCodeMap.REMOVE_RESOURCE,
                data: {
                  filePaths: [
                    "/storage/emulated/0/Download/mlkj-m180/resource/QQ截图20231231230503.png",
                    "/storage/emulated/0/Download/mlkj-m180/resource/000006/坐不下.mp4"
                  ]
                }
              });
              console.log("res: ", res);
            } catch (err) {
              console.log("err: ", err);
            }
          }}
        />
      </View>

      <Text style={styles.title}>定时操作</Text>
      <View style={styles.item}>
        <TextInput
          dense
          mode="outlined"
          label="cron表达式"
          placeholder="请输入cron表达式"
          value={state.cron}
          error={!state.cron}
          onChangeText={text => {
            setState("cron", text);
          }}
        />
        <Btn
          text="开始定时任务"
          type="primary"
          onClick={() => {
            if (job) {
              console.log("停止已经存在的cron实例", job);
              job.stop();
              return;
            }

            job = Cron(state.cron, () => {
              const time = new Date().toLocaleTimeString();
              console.log("cron run: ", time);
              setState("time", time);
            });
          }}
        />
        <Text>后台任务执行{state.time}</Text>
        <Btn
          text="停止定时任务"
          type="primary"
          onClick={() => {
            if (job) {
              job.stop();
              job = null;
              console.log("停止定时任务");
            }
          }}
        />
      </View>

      <Text style={styles.title}>自定义事件</Text>
      <View style={styles.item}>
        <Btn
          text="绑定hello事件"
          type="primary"
          onClick={() => {
            addListener("hello", e => {
              console.log("hello触发了: ", e);
            });
          }}
        />
        <Btn
          text="解绑hello事件"
          type="primary"
          onClick={() => {
            removeListener("hello");
          }}
        />
        <Btn
          text="触发hello事件"
          type="primary"
          onClick={() => {
            emit("hello", { msg: "测试的数据" });
          }}
        />
        <Btn
          text="事件相关对象"
          type="primary"
          onClick={() => {
            console.log("emitter: ", emitter);
            console.log("eventMap: ", eventMap);
          }}
        />
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10
  },
  title: { fontSize: 28, textAlign: "center" },
  item: {
    marginTop: 10,
    marginBottom: 10,
    display: "flex",
    flexDirection: "row",
    flexWrap: "wrap",
    gap: 10
  },
  dividerGap: {
    height: 10,
    marginBottom: 10
  }
});

export default SystemTest;
